<?php

namespace plugins\dfer_thinkcmf_tools\logic;

use app\admin\model\AdminMenuModel;
use app\admin\model\AuthRuleModel;
use think\facade\Env;
use mindplay\annotations\Annotations;

class MenuLogic
{
    /**
     * 导入应用所有菜单
     * 每次都会更新注释里的所有内容
     * @param $app
     * @param $is_plugin
     * @return array
     * @throws \ReflectionException
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public static function importMenusAll($app)
    {
        $app_arr=explode('/',$app);
        if(count($app_arr)>1){
            $is_plugin=true;
        }else{
            $is_plugin=false;
        }
        
        Annotations::$config['cache']                 = false;
        $annotationManager                            = Annotations::getManager();
        $annotationManager->registry['adminMenu']     = 'app\admin\annotation\AdminMenuAnnotation';
        $annotationManager->registry['adminMenuRoot'] = 'app\admin\annotation\AdminMenuRootAnnotation';
        $registry                                     = config('annotation.registry');

        if (empty($registry)) {
            $registry = ['date', 'email'];
        }

        foreach ($registry as $key => $value) {
            if (is_numeric($key)) {
                $annotationManager->registry[$value] = false;
            } else {
                $annotationManager->registry[$key] = $value;
            }
        }

        $newMenus = [];
        if($is_plugin){            
            $pluginDir = cmf_parse_name($app_arr[1]);       
            $filePatten = WEB_ROOT . 'plugins/' . $pluginDir . '/controller/Admin*Controller.php';
            }
            else{
                $filePatten  = APP_PATH . $app . '/controller/*Controller.php';
            }
        $controllers = cmf_scan_dir($filePatten);

        // var_dump($app,$controllers);die;
        if (!empty($controllers)) {
            foreach ($controllers as $controller) {
                // 判断控制器类型
                if (strpos($controller, "Admin") === 0 || $app == 'admin') {
                    $menu_type = 'admin_url';
                } else {
                    $menu_type = 'front_url';
                }

                $controller      = preg_replace('/\.php$/', '', $controller);
                $controllerName  = preg_replace("/Controller$/", '', $controller);
                if($is_plugin){
                    $controllerClass = "plugins\\$pluginDir\\controller\\$controller";
                }else{
                    $controllerClass = "app\\$app\\controller\\$controller";
                }
                try {
                    // 类注释
                    // 代码注释里的`@`符号会被解析，导致`// @unlink`这种写法会产生错误
                    $menuAnnotations = Annotations::ofClass($controllerClass, '@adminMenuRoot');
                } catch (\mindplay\annotations\AnnotationException $exception) {
                    $err_msg = $exception->getMessage();
                    dump([$controllerClass => $err_msg]);
                    break;
                } catch (Exception $exception) {
                }
                // var_dump($menuAnnotations);
                if (!empty($menuAnnotations)) {
                    foreach ($menuAnnotations as $menuAnnotation) {
                        $name      = $menuAnnotation->name;
                        $icon      = $menuAnnotation->icon;
                        $type      = 0; //1:有界面,2:无界面,0:只作为菜单
                        $action    = $menuAnnotation->action;
                        $status    = empty($menuAnnotation->display) ? 0 : 1;
                        $listOrder = floatval($menuAnnotation->order);
                        $param     = $menuAnnotation->param;
                        $remark    = $menuAnnotation->remark;

                        if (empty($menuAnnotation->parent)) {
                            $parentId = 0;
                        } else {
                            $parent      = explode('/', $menuAnnotation->parent);
                            $countParent = count($parent);
                            if ($countParent > 3) {
                                throw new \Exception($controllerClass . ':' . $action . '  @adminMenuRoot parent格式不正确!');
                            }

                            $parentApp        = $app;
                            $parentController = $controllerName;
                            $parentAction     = '';

                            switch ($countParent) {
                                case 1:
                                    $parentAction = $parent[0];
                                    break;
                                case 2:
                                    $parentController = $parent[0];
                                    $parentAction     = $parent[1];
                                    break;
                                case 3:
                                    $parentApp        = $parent[0];
                                    $parentController = $parent[1];
                                    $parentAction     = $parent[2];
                                    break;
                            }

                            // 获取父级id
                            $findParentAdminMenu = AdminMenuModel::where([
                                'app'        => $parentApp,
                                'controller' => $parentController,
                                'action'     => $parentAction
                            ])->find();

                            // 找不到父级，就创建父级
                            if (empty($findParentAdminMenu)) {
                                $parentId = AdminMenuModel::insertGetId([
                                    'app'        => $parentApp,
                                    'controller' => $parentController,
                                    'action'     => $parentAction,
                                    'name'       => '--new--'
                                ]);
                            } else {
                                $parentId = $findParentAdminMenu['id'];
                            }
                        }

                        $findAdminMenu = AdminMenuModel::where([
                            'app'        => $app,
                            'controller' => $controllerName,
                            'action'     => $action
                        ])->find();

                        if (empty($findAdminMenu)) {
                            // 新增
                            AdminMenuModel::insert([
                                'parent_id'  => $parentId,
                                'type'       => $type,
                                'status'     => $status,
                                'list_order' => $listOrder,
                                'app'        => $app,
                                'controller' => $controllerName,
                                'action'     => $action,
                                'param'      => $param,
                                'name'       => $name,
                                'icon'       => $icon,
                                'remark'     => $remark
                            ]);

                            $menuName = $name;

                            array_push($newMenus, "$app/$controllerName/$action 已导入");
                        } else {
                            // 更新
                            AdminMenuModel::where([
                                'app'        => $app,
                                'controller' => $controllerName,
                                'action'     => $action
                            ])->update([
                                'parent_id'  => $parentId,
                                'type'       => $type,
                                'status'     => $status,
                                'list_order' => $listOrder,
                                'param'      => $param,
                                'name'       => $name,
                                'icon'       => $icon,
                                'remark'     => $remark
                            ]);
                            $menuName = $findAdminMenu['name'];
                            array_push($newMenus, "$app/$controllerName/$action 层级关系已更新");
                        }

                        $authRuleName      = "{$app}/{$controllerName}/{$action}";
                        $findAuthRuleCount = AuthRuleModel::where([
                            'app'  => $app,
                            'name' => $authRuleName,
                            'type' => $menu_type
                        ])->count();

                        if ($findAuthRuleCount == 0) {
                            AuthRuleModel::insert([
                                'app'        => $app,
                                'name'       => $authRuleName,
                                'type'       => $menu_type,
                                'param'      => $param,
                                'title'      => $menuName,
                                'status'     => $status
                            ]);
                        } else {
                            AuthRuleModel::where([
                                'app'  => $app,
                                'name' => $authRuleName,
                                'type' => $menu_type,
                            ])->update([
                                'param'      => $param,
                                'title'      => $menuName,
                                'status'     => $status,
                            ]);
                        }
                    }
                }

                $reflect = new \ReflectionClass($controllerClass);
                $methods = $reflect->getMethods(\ReflectionMethod::IS_PUBLIC);
                // var_dump($methods,$controllerClass);
                if (!empty($methods)) {
                    foreach ($methods as $method) {
                        if ($method->class == $controllerClass && strpos($method->name, '_') !== 0) {
                            // 方法注释
                            $menuAnnotations = Annotations::ofMethod($controllerClass, $method->name, '@adminMenu');

                            if (!empty($menuAnnotations)) {
                                $menuAnnotation = $menuAnnotations[0];

                                $name      = $menuAnnotation->name;
                                $icon      = $menuAnnotation->icon;
                                $type      = $menuAnnotation->hasView ? 1 : 2; //1:有界面,2:无界面,0:只作为菜单
                                $action    = $method->name;
                                $status    = empty($menuAnnotation->display) ? 0 : 1;
                                $listOrder = floatval($menuAnnotation->order);
                                $param     = $menuAnnotation->param;
                                $remark    = $menuAnnotation->remark;

                                if (empty($menuAnnotation->parent)) {
                                    $parentId = 0;
                                } else {
                                    $parent      = explode('/', $menuAnnotation->parent);
                                    $countParent = count($parent);
                                    if ($countParent > 3) {
                                        throw new \Exception($controllerClass . ':' . $action . '  @menuRoot parent格式不正确!');
                                    }

                                    $parentApp        = $app;
                                    $parentController = $controllerName;
                                    $parentAction     = '';

                                    switch ($countParent) {
                                        case 1:
                                            $parentAction = $parent[0];
                                            break;
                                        case 2:
                                            $parentController = $parent[0];
                                            $parentAction     = $parent[1];
                                            break;
                                        case 3:
                                            $parentApp        = $parent[0];
                                            $parentController = $parent[1];
                                            $parentAction     = $parent[2];
                                            break;
                                    }

                                    $findParentAdminMenu = AdminMenuModel::where([
                                        'app'        => $parentApp,
                                        'controller' => $parentController,
                                        'action'     => $parentAction
                                    ])->find();

                                    // 找不到父级，就创建父级
                                    if (empty($findParentAdminMenu)) {
                                        $parentId = AdminMenuModel::insertGetId([
                                            'app'        => $parentApp,
                                            'controller' => $parentController,
                                            'action'     => $parentAction,
                                            'name'       => '--new--'
                                        ]);
                                    } else {
                                        $parentId = $findParentAdminMenu['id'];
                                    }
                                }

                                $findAdminMenu = AdminMenuModel::where([
                                    'app'        => $app,
                                    'controller' => $controllerName,
                                    'action'     => $action
                                ])->find();

                                if (empty($findAdminMenu)) {
                                    AdminMenuModel::insert([
                                        'parent_id'  => $parentId,
                                        'type'       => $type,
                                        'status'     => $status,
                                        'list_order' => $listOrder,
                                        'app'        => $app,
                                        'controller' => $controllerName,
                                        'action'     => $action,
                                        'param'      => $param,
                                        'name'       => $name,
                                        'icon'       => $icon,
                                        'remark'     => $remark
                                    ]);

                                    $menuName = $name;

                                    array_push($newMenus, "$app/$controllerName/$action 已导入");
                                } else {
                                    AdminMenuModel::where([
                                        'app'        => $app,
                                        'controller' => $controllerName,
                                        'action'     => $action
                                    ])->update([
                                        'parent_id'  => $parentId,
                                        'type'       => $type,
                                        'status'     => $status,
                                        'list_order' => $listOrder,
                                        'param'      => $param,
                                        'name'       => $name,
                                        'icon'       => $icon,
                                        'remark'     => $remark
                                    ]);
                                    $menuName = $findAdminMenu['name'];

                                    array_push($newMenus, "$app/$controllerName/$action 已更新");
                                }

                                $authRuleName      = "{$app}/{$controllerName}/{$action}";
                                $findAuthRuleCount = AuthRuleModel::where([
                                    'app'  => $app,
                                    'name' => $authRuleName,
                                    'type' => $menu_type
                                ])->count();

                                if ($findAuthRuleCount == 0) {
                                    AuthRuleModel::insert([
                                        'app'        => $app,
                                        'name'       => $authRuleName,
                                        'type'       => $menu_type,
                                        'param'      => $param,
                                        'title'      => $menuName,
                                        'status'     => $status,
                                    ]);
                                } else {
                                    AuthRuleModel::where([
                                        'app'  => $app,
                                        'name' => $authRuleName,
                                        'type' => $menu_type,
                                    ])->update([
                                        'param'      => $param,
                                        'title'      => $menuName,
                                        'status'     => $status,
                                    ]);
                                }
                            }
                        }
                    }
                }
            }
        }

        return $newMenus;
    }
}
